package com.example.common.utils.litesql;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import androidx.annotation.Nullable;

import com.coszero.utilslibrary.utils.LogX;

import org.litepal.LitePal;
import org.litepal.crud.LitePalSupport;
import org.litepal.tablemanager.Connector;

import java.util.List;

/**
 * Desc： 数据库工具类 LitePal数据库
 *
 * @author xmqian
 * Email:xmqian93@163.com
 * Date: 2020/9/4 0004 10:59
 * @version org.litepal.guolindev:core:3.2.1
 * #    ###save:存储数据
 * Album album = new Album();
 * album.setName("album");
 * album.setPrice(10.99f);
 * album.setCover(getCoverImageBytes());
 * album.save();
 * #    ###update:更新数据
 * Album albumToUpdate = LitePal.find(Album.class, 1);
 * albumToUpdate.setPrice(20.99f); // raise the price
 * albumToUpdate.save();
 * #    ##update:更新指定id数据,使用update(id)或者updateAll()
 * Album albumToUpdate = new Album();
 * albumToUpdate.setPrice(20.99f); // raise the price
 * albumToUpdate.update(id);
 * albumToUpdate.updateAll();
 * #    ##updates:更新多条信息
 * Album albumToUpdate = new Album();
 * albumToUpdate.setPrice(20.99f); // raise the price
 * albumToUpdate.updateAll("name = ?", "album");
 * #    ##delete:删除单个数据
 * LitePal.delete(Song.class, id);
 * #    ##delete:删除多个条件数据,如 duration>350的所有数据
 * LitePal.deleteAll<Song>("duration > ?" , "350")
 * #    ##find:查询数据
 * Song song = LitePal.find(Song.class, id);
 * #    ##find:查询所有数据
 * List<Song> allSongs = LitePal.findAll(Song.class);
 * #    ##find:查询条件数据
 * List<Song> songs = LitePal.where("name like ? and duration < ?", "song%", "200").order("duration").find(Song.class);
 * #    ##crete:使用指定的表创建一个新数据库
 * LitePalDB LitePalDB = new LitePalDB("demo2", 1);
 * LitePalDB.addClassName(Singer.class.getName());
 * LitePalDB.addClassName(Album.class.getName());
 * LitePalDB.addClassName(Song.class.getName());
 * LitePal.use(LitePalDB);
 * #    ##crete:创建一个与配置文件数据库相同的数据库
 * LitePalDB LitePalDB = LitePalDB.fromDefault("newdb");
 * LitePal.use(LitePalDB);
 * #    ##switch：切换为默认数据库
 * LitePal.useDefault();
 */
public class LiteUtils {
    private static final String TAG = "LiteSqlUtils";

    public static void init(Context context) {
        LitePal.initialize(context);
    }

    // <editor-fold desc="增" defaultstate="collapsed">

    /**
     * 主动创建数据库表,即使是没有使用save,也能建立个空表出来
     */
    public static SQLiteDatabase create() {
        return Connector.getDatabase();
    }

    /**
     * 存储多条数据,比单条循环存储要快
     *
     * @param list 多条数据同时存储
     * @return 是否存储成功
     */
    public static boolean saveAll(List<? extends LitePalSupport> list) {
        return LitePal.saveAll(list);
    }
//</editor-fold>

    // <editor-fold desc="查" defaultstate="collapsed">

    /**
     * 查找单个数据
     *
     * @param mClass 表名称，通常是实体类的class类型
     * @param id 位置键值
     * @param <T> T
     * @return 返回查找的信息
     */
    public static <T> T find(Class<T> mClass, long id) {
        return LitePal.find(mClass, id);
    }

    /**
     * 指定条件查询多列相等的数据
     * 取出其中一列匹配的数据
     *
     * @param mClass class
     * @param key 键
     * @param value 值
     * @param <T> T
     * @return 配置该值得数据
     */
    public static <T> List<T> findColumnsEqualOr(Class<T> mClass, String value, String... key) {
        StringBuilder builder = new StringBuilder();
        String[] conditions = new String[key.length + 1];
        int index = 0;
        for (String columnName : key) {
            index++;
            builder.append(" " + columnName + " = ? or");
            conditions[index] = value;
        }
        String keys = builder.substring(0, builder.length() - 2);
        conditions[0] = keys;
        LogX.i(TAG, "数据可多列查询指令：" + keys);
        List<T> arrays = LitePal.where(conditions).find(mClass);
        return arrays;
    }

    /**
     * 指定条件查询多列模糊搜索的数据
     * 取出多列匹配的数据
     *
     * @param mClass class
     * @param key 键
     * @param value 值
     * @param <T> T
     * @return 配置该值得数据
     */
    public static <T> List<T> findColumnsAlikeOr(Class<T> mClass, String value, String... key) {
        StringBuilder builder = new StringBuilder();
        String[] conditions = new String[key.length + 1];
        int index = 0;
        for (String columnName : key) {
            index++;
            builder.append(" " + columnName + " like ? or");
            conditions[index] = "%" + value + "%";
        }
        String keys = builder.substring(0, builder.length() - 2);
        conditions[0] = keys;
        LogX.i(TAG, "数据可多列查询指令：" + keys);
        List<T> arrays = LitePal.where(conditions).find(mClass);
        return arrays;
    }

    /**
     * @param mClass mClass
     * @param conditions 命令字符串，输入的命令包含列名，值，条件信息，格式为 条件,值，值，值
     * @param <T> T
     * @return 返回执行查询命令后的结果
     */
    public static <T> List<T> findColumns(Class<T> mClass, String... conditions) {
        return LitePal.where(conditions).find(mClass);
    }

    /**
     * @param desc true 倒序
     */
    public static <T> List<T> findColumnsOrder(Class<T> mClass, String orderColumnName, boolean desc, String... conditions) {
        return LitePal.where(conditions).order(orderColumnName + (desc ? " desc" : " asc")).find(mClass);
    }

    /**
     * 查找指定条件的数据
     *
     * @param mClass class
     * @param key 键
     * @param value 值
     * @param <T> T
     * @return 配置该值得数据
     */
    public static <T> List<T> find(Class<T> mClass, String key, String value) {
        List<T> arrays = LitePal.where(key + " = ?", value).find(mClass);
        return arrays;
    }


    /**
     * @param mClass class
     * @param <T> T
     * @return 返回所有数据
     */
    public static <T> List<T> find(Class<T> mClass) {
        return LitePal.findAll(mClass);
    }

    /**
     * @param mClass class
     * @param <T> T
     * @return 返回降序查询结果
     */
    public static <T> List<T> findOrder(Class<T> mClass) {
        return LitePal.order("ID desc").find(mClass);
    }

    /**
     * @param mClass class
     * @param key key
     * @param value value
     * @param orderKey 需要排序的列
     * @param <T> T
     * @return 返回降序查询结果
     */
    public static <T> List<T> findOrder(Class<T> mClass, String key, String value, String orderKey) {
        return LitePal.where(key + " = ?", value).order(orderKey + " desc").find(mClass);
    }

    /**
     * @param mClass class
     * @param orderKey 排序的列
     * @param conditions 条件命令 条件，值，值
     * @param <T> T
     * @return 返回符合条件的数据
     */
    public static <T> List<T> findOrder(Class<T> mClass, String orderKey, String... conditions) {
        return LitePal.where(conditions).order(orderKey + " desc").find(mClass);
    }

    /**
     * 分页查询
     *
     * @param mClass class
     * @param rows 每页条数
     * @param page 页数
     * @param <T> T
     */
    public static <T> List<T> findLimit(Class<T> mClass, int rows, int page) {
        return LitePal.limit(rows).offset(page * rows).find(mClass);
    }

    /**
     * @param mClass class
     * @param rows rows
     * @param page page
     * @param conditions 命令,命令，值，值， 有几个条件就有几个值，一一对应
     * @param <T> T
     * @return 返回条件查询后分页结果
     */
    public static <T> List<T> findLimitWhere(Class<T> mClass, int rows, int page, String... conditions) {
        return LitePal.where(conditions).limit(rows).offset(page * rows).find(mClass);
    }

    public static <T> List<T> findLimitWhereOrder(Class<T> mClass, int rows, int page, String... conditions) {
        return LitePal.where(conditions).order("ID desc").limit(rows).offset(page * rows).find(mClass);
    }

    /**
     * @param mClass class
     * @param rows rows
     * @param page page
     * @param <T> T
     * @return 返回倒序分页数据
     */
    public static <T> List<T> findLimitOrder(Class<T> mClass, int rows, int page) {
        return LitePal.order("ID desc").limit(rows).offset(page * rows).find(mClass);
    }

    /**
     * @param mClass class
     * @param <T> T
     * @return 返回该表中有多少条数据
     */
    public static <T> int count(Class<T> mClass) {
        return LitePal.count(mClass);
    }

    /**
     * @param mClass class
     * @param conditions 命令：条件,值，值 例如 con>? or lit < ?,1,100
     * @param <T> T
     * @return 返回符合查询条件的数量
     */
    public static <T> int countWhere(Class<T> mClass, String... conditions) {
        return LitePal.where(conditions).count(mClass);
    }
    //</editor-fold>

    // <editor-fold desc="删" defaultstate="collapsed">
    public static <T> int clear(Class<T> mClass) {
        return LitePal.deleteAll(mClass);
    }
    //</editor-fold>

    // <editor-fold desc="改" defaultstate="collapsed">

    /**
     * 更新指定id的数据
     *
     * @param mClass mClass
     * @param contentValues ContentValues contentValues = new ContentValues();
     * contentValues.put("key","value");
     * @param id 数据库键值id
     * @param <T> T
     * @return id
     */
    public static <T> int updateId(Class<T> mClass, ContentValues contentValues, long id) {
        return LitePal.update(mClass, contentValues, id);
    }

    /**
     * 更新符合条件的数据
     * where参数可为null,为null时修改所有数据
     *
     * @param mClass mClass
     * @param contentValues contentValues
     * @param where 条件语句 "title = ?", "今日iPhone6发布" 单条件
     * title = ? and commentcount > ?", "今日iPhone6发布", "0" 多条件，有几个问号后面就应该接几个结果
     * @param <T> T
     * @return 返回修改了多少条数据
     */
    public static <T> int updateAll(Class<T> mClass, ContentValues contentValues, @Nullable String... where) {
        if (where == null) {
            return LitePal.updateAll(mClass, contentValues);
        }
        return LitePal.updateAll(mClass, contentValues, where);
    }
    //</editor-fold>

    public static <T> boolean exists(Class<T> mClass) {
        return LitePal.isExist(mClass, "");
    }
}
